<?php
/**
 * @package Waterwheel
 */
/* 
 *  Copyright 2010 Andrew Rickmann
 * 
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 * 
 *  http://www.apache.org/licenses/LICENSE-2.0
 * 
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
require_once(dirname(__FILE__) . '/simpletest/autorun.php');

/**
 *
 * Finds the file the given class name and includes it ready for the class to be instantiated.
 * This is passed to the spl_autoload_register function to automate the process.
 *
 * @param String $classname The name of the class being instantiated.
 */
function application_autoload($classname){
	$path = APPLICATION_PATH . "/../classes" . DIRECTORY_SEPARATOR;
	$file = $path . $classname . '.php';
	if( file_exists($file) ){
		include_once($file);
	}
}

//setup the class autoloader
spl_autoload_register('application_autoload');

define('APPLICATION_PATH' , dirname(__FILE__) );

/**
 * Test of Database Connection
 *
 * @author Andrew Rickmann
 */
class TestOfDatabaseConnection extends UnitTestCase {

    /**
     * D before tests
     */
    function setUp() {

    }

    /**
     * Do after tests
     */
    function tearDown() {
        
    }

    function xtestLackOfConnectionInformation(){

	//rename the connection data file
	rename( APPLICATION_PATH . '/connectiondata.xml', APPLICATION_PATH . '/connectiondatax.xml' );

	//create a new database connection
	try {
	    databaseconnection::singleton();
	    $this->fail('An exception was expected');
	} catch( waterwheelexception $e ){
	    if ( $e->getMessage() == 'No database connection information available.' ){
		$this->pass();
	    } else {
		$this->fail('The expected exception was different. We got: ' . $e->getMessage());
	    }
	}
	
	//name the file back again
	rename( APPLICATION_PATH . '/connectiondatax.xml', APPLICATION_PATH . '/connectiondata.xml' );

    }

    function xtestMissingDatabase(){

	//open file and check that the connection information is
	$filedata = file_get_contents(APPLICATION_PATH . '/connectiondata.xml');

	//convert it to XML
	$xmlconnectiondata = new SimpleXMLElement($filedata);

	//change the host information
	$xmlconnectiondata->host = 'noconnectiondata';

	//save the new file
	file_put_contents(APPLICATION_PATH . '/connectiondata.xml' , $xmlconnectiondata->asXML());

	//do the tests
	try {
	    databaseconnection::singleton();
	    $this->fail('An exception was expected');
	} catch( waterwheelexception $e ){
	    if ( $e->getMessage() == 'No database connection available.' ){
		$this->pass();
	    } else {
		$this->fail('The expected exception was different. We got: ' . $e->getMessage());
	    }
	}

	//put the correct connection data back again
	file_put_contents(APPLICATION_PATH . '/connectiondata.xml' , $filedata);

    }

    function testQuerySingleRow(){

	//basic query which instructs the database to return a known value
	$test_sql = "SELECT 1+1 as added";

	$result = databaseconnection::query($test_sql);

	//check that result is an array
	$this->assertTrue(is_array($result) , 'query returns an array');

	//check that the row item is also an array
	$this->assertTrue(is_array($result[0]), 'Rows returned by query are themselves arrays');

	//check the result
	$this->assertTrue($result[0]['added'] == 2 , 'Queries returned is result expected' );


    }

    function testQueryScalar(){

	//basic query which instructs the database to return a known value
	$test_sql = "SELECT 1+1 as added";

	$result = databaseconnection::queryScalar($test_sql);

	//check that result is not an array
	$this->assertFalse(is_array($result) , 'Query Scalar does not return an array');

	//check the result
	$this->assertTrue($result == 2 , 'QueryScalar returned the result expected');
    }

    function testQueryScalarParams(){

	//basic query which instructs the database to return a known value
	$test_sql = "SELECT ? + ? as added";
	$test_sql_params = array(2,2);

	$result = databaseconnection::queryScalar($test_sql , $test_sql_params);

	//check the result
	$this->assertTrue($result == 4 , 'QueryScalar with parameters returned the expected result');

    }

    function testExec(){

	//create a table
	$create_table_sql = 'CREATE  TABLE IF NOT EXISTS `waterwheel_test`.`generic_table` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  `name` VARCHAR(45) NOT NULL ,
  PRIMARY KEY (`id`) );';

	$exec_val = databaseconnection::exec($create_table_sql);

	//no rows affected. Should return false if the query did not work
	$this->assertTrue( $exec_val === 0 , 'The exec query returned zero affected rows for a create table statement' );

	//insert something into the table
	$insert_sql = "INSERT INTO `generic_table` (`name`) VALUES ('TESTVALUE')";

	$exec_val = databaseconnection::exec($insert_sql);

	//one rows affected.
	$this->assertTrue( $exec_val === 1 , 'The exec query returned the expected number of rows for an insert statement' );

	//retrieve it to test it worked
	$get_name_sql = "SELECT `name` FROM `generic_table` WHERE `name` = 'TESTVALUE'";
	$name = databaseconnection::queryScalar($get_name_sql);

	$this->assertTrue( $name == 'TESTVALUE' , 'The value inserted into the table using the exec statement was successfully retrieved' );

	//drop the table again
	$drop_sql = 'DROP TABLE `generic_table`';
	databaseconnection::exec($drop_sql);

    }


    function testTableExists(){

	//create a table
	$create_table_sql = 'CREATE  TABLE IF NOT EXISTS `waterwheel_test`.`generic_table` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  `name` VARCHAR(45) NOT NULL ,
  PRIMARY KEY (`id`) );';

	$exec_val = databaseconnection::exec($create_table_sql);

	$this->assertTrue( databaseconnection::table_exists('generic_table') , 'The table exists' );

	//drop the table again
	$drop_sql = 'DROP TABLE `generic_table`';
	databaseconnection::exec($drop_sql);

    }

    function testTableExistsWithNoTable(){

	$this->assertFalse( databaseconnection::table_exists('non_existant_table') , 'The table does not exist' );
    }


    function testTableColumns(){

	//create a table
	$create_table_sql = 'CREATE  TABLE IF NOT EXISTS `waterwheel_test`.`generic_table` (
  `id` INT(11) NOT NULL AUTO_INCREMENT ,
  `name` VARCHAR(45) NOT NULL ,
  PRIMARY KEY (`id`) );';

	$exec_val = databaseconnection::exec($create_table_sql);

	$cols = databaseconnection::table_columns('generic_table');

	//we are expecting an array of arrays, with the key of the array being the column name
	$this->assertTrue( is_array( $cols ) );
	$this->assertTrue( is_array( $cols['id'] ) , 'Test that the result array contains arrays');

	//this table has two columns so make sure the count is correct
	$this->assertEqual(count($cols), 2);

	//the first column should be named id of type INT
	$this->assertEqual($cols['id']['name'], 'id');
	$this->assertEqual($cols['id']['type'], 'int(11)');

	//the first column should be named name of type varchar(45)
	$this->assertEqual($cols['name']['name'], 'name');
	$this->assertEqual($cols['name']['type'], 'varchar(45)');

	//drop the table again
	$drop_sql = 'DROP TABLE `generic_table`';
	databaseconnection::exec($drop_sql);

    }

    function testTableColumnsWhereTableDoesNotExist(){

	$cols = databaseconnection::table_columns('notableexistswiththisname');

	$this->assertFalse($cols);

    }



}

?>